<template>
  <div class="container">
    <div class="top-controls">
      <input type="file" @change="handleFileUpload" accept=".docx" />
    </div>
    <div class="main-content">
      <div class="left-panel">
        <ul v-if="tableOfContents.length">
          <TocItem 
            v-for="(item, index) in tableOfContents" 
            :key="item.id" 
            :item="item" 
            :on-scroll="scrollToSection" 
          />
        </ul>
      </div>
      <div class="right-panel">
        <WangEditorVue 
        v-model="editorContent" 
        placeholder="请输入富文本内容..." 
      />
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref,onMounted, nextTick, watch } from 'vue';
import mammoth from 'mammoth';
import WangEditor from './components/WangEditor.vue';
import WangEditorVue from './components/WangEditorVue.vue';
import TocItem from './components/TocItem.vue';

const editorContent = ref(''); // 存储编辑器内容
const originContent = ref(''); // 存储原始HTML内容


const tableOfContents = ref([]);
const sections = ref([]);

// 监听编辑器内容变化，重新解析文档结构
// watch(editorContent, (newContent) => {
//   console.log(newContent);
//   parseDocument(newContent);
// });

const options = {
  // 样式映射配置 - 将Word中的样式映射到HTML元素和类
  styleMap: [
    // 标题样式映射
    "p[style-name='Heading 1'] => h1.heading1",
    "p[style-name='Heading 2'] => h2.heading2",
    "p[style-name='Heading 3'] => h3.heading3",
    "p[style-name='Heading 4'] => h4.heading4",
    "p[style-name='Heading 5'] => h5.heading5",
    "p[style-name='Heading 6'] => h6.heading6",
    "p => p:fresh",
    // 正文样式
    // 处理段落对齐
    
    "p[alignment=center] => p:fresh { text-align: center; }",
    "p[alignment=right] => p:fresh { text-align: right; }",
    "p[alignment=both] => p:fresh { text-align: justify; }",
    
    // 处理缩进
    "p[style-name='首行缩进'] => p:fresh { text-indent: 2em; }",
    "p[style-name='左缩进'] => p:fresh { padding-left: 2em; }",
    
    // 特殊文本样式
    "r[style-name='Emphasis'] => span.emphasis",
    "r[style-name='Strong'] => span.strong",
    "r[style-name='Blue Text'] => span.blue-text",
    
    // 表格样式
    "table[style-name='Table Grid'] => table.table-grid",
    "table[style-name='Light Shading'] => table.light-shading",
    
    // 列表样式
    "ol => ol.list-ordered",
    "ul => ul.list-unordered",
    "li => li"
  ],
  
  // 表格样式映射 - 专门处理表格元素
  tableStyleMap: [
    "table[style-name='表格'] => table",
    "tr[style-name='表格行'] => tr",
    "td[style-name='表格单元格'] => td",
    "th[style-name='表格标题'] => th"
  ],
  
  // 保留Word文档中的原始样式属性
  includeDefaultStyleMap: true,
  includeEmbeddedStyleMap: true,
  // ignoreEmptyParagraphs:  true,
  transformDocument: function(documentElement) {
    console.log(documentElement);
    // 递归遍历所有节点
    function processNode(node) {
      if (node.type === "paragraph") {
        // 创建或合并现有样式属性
        const style = {};
        
        // 处理对齐方式
        if (node.alignment) {
          let textAlign;
          switch (node.alignment) {
            case "center": textAlign = "center"; break;
            case "right": textAlign = "right"; break;
            case "both": textAlign = "justify"; break;
            default: textAlign = "left";
          }
          style["text-align"] = textAlign;
        }
        
        // 处理首行缩进（twip 转像素，假设96DPI）
        if (node.firstLineIndent) {
          const indentInPx = Math.round(node.firstLineIndent / 1440 * 96);
          style["text-indent"] = `${indentInPx}px`;
        }
        
        // 处理左缩进
        if (node.leftIndent) {
          const leftIndentInPx = Math.round(node.leftIndent / 1440 * 96);
          style["padding-left"] = `${leftIndentInPx}px`;
        }
        
        // 应用样式
        if (Object.keys(style).length > 0) {
          node.attributes = node.attributes || {};
          const existingStyle = node.attributes.style || "";
          const newStyle = Object.entries(style)
            .map(([key, value]) => `${key}: ${value}`)
            .join("; ");
          
          node.attributes.style = existingStyle 
            ? `${existingStyle}; ${newStyle}` 
            : newStyle;
        }
      }
      
      // 递归处理子节点
      if (node.children) {
        node.children = node.children.map(processNode);
      }
      return node;
    }
    
    // 处理整个文档树
    return processNode(documentElement);
  },
  // 图片转换配置
  convertImage: mammoth.images.imgElement(async function(image) {
    const imageBuffer = await image.read('base64');
    const dimensions = getImageDimensionsFromBase64(imageBuffer);
    return {
      src: `data:${image.contentType};base64,${imageBuffer}`,
      style: `width: ${dimensions.width}px; height: ${dimensions.height}px;` 
    };
  }),
  
  // 表格样式覆盖
  tableStyleOverride: function(table) {
    // 为所有表格添加自定义类
    return {
      className: "custom-table"
    };
  },
  
  // 列表转换配置
  list: {
    // 自定义列表项处理
    startNumbering: function() {
      return {
        // 重置有序列表计数
        start: 1
      };
    }
  },
  
  // 链接处理
  link: function(element) {
    // 保留原始链接并添加target="_blank"
    return {
      attributes: {
        href: element.href,
        target: "_blank"
      }
    };
  }
};

// 定义辅助函数：将twip转换为像素（1twip = 1/1440英寸）
function getImageDimensionsFromBase64(base64String) {
  // 移除Data URI前缀
  const pureBase64 = base64String.replace(/^data:image\/[a-z]+;base64,/, '');
  const binary = atob(pureBase64);
  
  // 检查图片类型
  if (binary.startsWith('\xFF\xD8')) { // JPEG
    return getJpegDimensions(binary);
  } else if (binary.startsWith('\x89PNG\r\n\x1A\n')) { // PNG
    return getPngDimensions(binary);
  } else if (binary.startsWith('GIF87a') || binary.startsWith('GIF89a')) { // GIF
    return {
      width: (binary.charCodeAt(6) | (binary.charCodeAt(7) << 8)),
      height: (binary.charCodeAt(8) | (binary.charCodeAt(9) << 8))
    };
  } else {
    throw new Error('不支持的图片格式');
  }
}
function getJpegDimensions(binary) {
  // 简化版JPEG解析（仅处理常见情况）
  let i = 4;
  while (i < binary.length) {
    const marker = (binary.charCodeAt(i) << 8) | binary.charCodeAt(i + 1);
    
    if (marker >= 0xFFC0 && marker <= 0xFFCF && marker !== 0xFFC4 && marker !== 0xFFC8) {
      return {
        height: (binary.charCodeAt(i + 5) << 8) | binary.charCodeAt(i + 6),
        width: (binary.charCodeAt(i + 7) << 8) | binary.charCodeAt(i + 8)
      };
    }
    
    i += 2 + ((binary.charCodeAt(i + 2) << 8) | binary.charCodeAt(i + 3));
  }
  
  throw new Error('无法解析JPEG尺寸');
}

function getPngDimensions(binary) {
  // PNG尺寸在第16-19字节（宽度）和20-23字节（高度）
  return {
    width: (binary.charCodeAt(16) << 24) | (binary.charCodeAt(17) << 16) | 
           (binary.charCodeAt(18) << 8) | binary.charCodeAt(19),
    height: (binary.charCodeAt(20) << 24) | (binary.charCodeAt(21) << 16) | 
            (binary.charCodeAt(22) << 8) | binary.charCodeAt(23)
  };
}


const handleFileUpload = async (e) => {
  const file = e.target.files[0];
  if (!file) return;

  const reader = new FileReader();
  reader.onload = async (event) => {
    const arrayBuffer = event.target.result;
    const result = await mammoth.convertToHtml({ arrayBuffer }, options);
    console.log("Result:", result.value);
    parseDocument(result.value);
  };
  reader.readAsArrayBuffer(file);
};

const parseDocument = (htmlContent) => {
  originContent.value = htmlContent;
  const newSections = [];
  const toc = [];
  let currentLevel = 0;
  const stack = [toc]; // 栈初始化为根目录数组
  const tempDiv = document.createElement('div');
  tempDiv.innerHTML = htmlContent;
  const elements = tempDiv.children;

  Array.from(elements).forEach((element, index) => {
    const level = getHeadingLevel(element.tagName);
    const id = `section-${index}`;

    if (level > 0) {
      element.id = id; // 为标题元素设置唯一id
      const title = element.textContent;
      const section = {
        id,
        level,
        title,
        content: '',
        children: []
      };

      // 调整栈长度匹配当前层级
      while (stack.length > level) stack.pop();
      const currentParent = stack[stack.length - 1]; // 获取当前层级的父级数组

      currentParent.push(section); // 添加到正确父级
      newSections.push(section);

      // 推送当前章节的子数组到栈，供下一级标题使用
      stack.push(section.children);

      currentLevel = level;
    } else {
      if (newSections.length > 0) {
        newSections[newSections.length - 1].content += element.outerHTML;
      }
    }
  });
  tableOfContents.value = toc;
  tableOfContents.value.unshift({
   children: [],content: "",id: "1",level: 1,title: "全文" 
  })
  sections.value = newSections;
  sections.value.unshift({
   children: [],content: "",id: "1",level: 1,title: "全文" 
  })
  editorContent.value = htmlContent; // 初始化编辑器内容为原始HTML
};

const getHeadingLevel = (tagName) => {
  if (tagName.startsWith('H') && tagName.length === 2) {
    return parseInt(tagName[1], 10);
  }
  return 0;
};

const scrollToSection = (id) => {
    // 查找对应的章节内容并更新编辑器，包含标题
    const section = sections.value.find(s => s.id === id);
    if (section) {
      if (!section.content && section.children && section.children.length == 0 && section.level == 1) {
        editorContent.value = originContent.value; // 清空编辑器内容
      } else {
        const headingTag = `h${section.level}`;
        const headingHtml = `<${headingTag}>${section.title}</${headingTag}>`;
        let contentHtml = section.content;

        // 递归生成多级子章节内容
        const generateContent = (node) => {
          const headingTag = `h${node.level}`;
          let html = `<${headingTag}>${node.title}</${headingTag}>`;
          html += node.content;
          if (node.children && node.children.length > 0) {
            html += node.children.map(child => generateContent(child)).join('');
          }
          return html;
        };

        // 处理content为空但有子章节的情况
        if (section.children && section.children.length > 0) {
          contentHtml = section.children.map(child => generateContent(child)).join('');
        }

        editorContent.value = headingHtml + contentHtml;
      }
    }
};




</script>

<style scoped>
.top-controls {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-bottom: 20px;
}

.export-btn {
  padding: 8px 16px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.export-btn:hover {
  background: #0056b3;
  text-decoration: none;
}

.container {
  padding: 20px;
}

.main-content {
  display: flex;
  margin-top: 20px;
  gap: 20px;
}

.left-panel {
  flex: 1;
  max-width: 300px;
  border-right: 1px solid #ccc;
  padding-right: 20px;
}

.right-panel {
  flex: 3;
}

button {
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  color: #007bff;
  margin: 5px 0;
}

button:hover {
  text-decoration: underline;
}

ul {
  list-style-type: none;
  padding-left: 20px;
}

.toolbar {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  margin-bottom: 10px;
}

.editor {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  min-height: 500px;
  padding: 15px;
}
</style>

<style>
/* 全局样式确保v-html中的表格正确显示 */
.right-panel table {
  border-collapse: collapse;
  width: 100%;
  margin: 10px 0;
}
.right-panel td, .right-panel th {
  border: 1px solid #ddd;
  padding: 8px;
}
.right-panel tr:nth-child(even) {
  background-color: #f2f2f2;
}
  .right-panel p {
    margin: 10px 0;
    line-height: 1.6;
    font-size: 16px;
  }
</style>